home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / CONES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-18  |  19.4 KB  |  1,071 lines

  1. /****************************************************************************
  2. *                cones.c
  3. *
  4. *  This module implements the cone primitive.
  5. *  This file was written by Alexander Enzmann.    He wrote the code for
  6. *  cones and generously provided us these enhancements.
  7. *
  8. *  from Persistence of Vision(tm) Ray Tracer
  9. *  Copyright 1996 Persistence of Vision Team
  10. *---------------------------------------------------------------------------
  11. *  NOTICE: This source code file is provided so that users may experiment
  12. *  with enhancements to POV-Ray and to port the software to platforms other 
  13. *  than those supported by the POV-Ray Team.  There are strict rules under
  14. *  which you are permitted to use this file.  The rules are in the file
  15. *  named POVLEGAL.DOC which should be distributed with this file. If 
  16. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  18. *  Forum.  The latest version of POV-Ray may be found there as well.
  19. *
  20. * This program is based on the popular DKB raytracer version 2.12.
  21. * DKBTrace was originally written by David K. Buck.
  22. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  23. *
  24. *****************************************************************************/
  25.  
  26. #include "frame.h"
  27. #include "povray.h"
  28. #include "vector.h"
  29. #include "povproto.h"
  30. #include "bbox.h"
  31. #include "cones.h"
  32. #include "matrices.h"
  33. #include "objects.h"
  34.  
  35.  
  36.  
  37. /*****************************************************************************
  38. * Local preprocessor defines
  39. ******************************************************************************/
  40.  
  41. #define Cone_Tolerance 1.0e-6
  42.  
  43. #define close(x, y) (fabs(x-y) < EPSILON ? 1 : 0)
  44.  
  45. /* Part of the cone/cylinder hit. [DB 9/94] */
  46.  
  47. #define BASE_HIT 1
  48. #define CAP_HIT  2
  49. #define SIDE_HIT 3
  50.  
  51.  
  52.  
  53. /*****************************************************************************
  54. * Local typedefs
  55. ******************************************************************************/
  56.  
  57. typedef struct Cone_Intersection_Structure CONE_INT;
  58.  
  59. struct Cone_Intersection_Structure
  60. {
  61.   DBL d;  /* Distance of intersection point               */
  62.   int t;  /* Type of intersection: base/cap plane or side */
  63. };
  64.  
  65.  
  66.  
  67. /*****************************************************************************
  68. * Static functions
  69. ******************************************************************************/
  70.  
  71. static int intersect_cone PARAMS((RAY *Ray, CONE *Cone, CONE_INT *Depths));
  72. static void Destroy_Cone PARAMS((OBJECT *Object));
  73. static int All_Cone_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
  74. static int Inside_Cone PARAMS((VECTOR point, OBJECT *Object));
  75. static void Cone_Normal PARAMS((VECTOR Result, OBJECT *Object, INTERSECTION *Inter));
  76. static void *Copy_Cone PARAMS((OBJECT *Object));
  77. static void Translate_Cone PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  78. static void Rotate_Cone PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  79. static void Scale_Cone PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  80. static void Transform_Cone PARAMS((OBJECT *Object, TRANSFORM *Trans));
  81. static void Invert_Cone PARAMS((OBJECT *Object));
  82.  
  83.  
  84. /*****************************************************************************
  85. * Local variables
  86. ******************************************************************************/
  87.  
  88. static METHODS Cone_Methods =
  89. {
  90.   All_Cone_Intersections,
  91.   Inside_Cone, Cone_Normal,
  92.   Copy_Cone, Translate_Cone, Rotate_Cone, Scale_Cone, Transform_Cone,
  93.   Invert_Cone, Destroy_Cone
  94. };
  95.  
  96.  
  97.  
  98. /*****************************************************************************
  99. *
  100. * FUNCTION
  101. *
  102. *   All_Cone_Intersections
  103. *
  104. * INPUT
  105. *   
  106. * OUTPUT
  107. *   
  108. * RETURNS
  109. *   
  110. * AUTHOR
  111. *
  112. *   Alexander Enzmann
  113. *   
  114. * DESCRIPTION
  115. *
  116. *   -
  117. *
  118. * CHANGES
  119. *
  120. *   -
  121. *
  122. ******************************************************************************/
  123.  
  124. static int All_Cone_Intersections(Object, Ray, Depth_Stack)
  125. OBJECT *Object;
  126. RAY *Ray;
  127. ISTACK *Depth_Stack;
  128. {
  129.   int Intersection_Found, cnt, i;
  130.   VECTOR IPoint;
  131.   CONE_INT I[4];
  132.  
  133.   Intersection_Found = FALSE;
  134.  
  135.   if ((cnt = intersect_cone(Ray, (CONE *)Object, I)) != 0)
  136.   {
  137.     for (i = 0; i < cnt; i++)
  138.     {
  139.       VEvaluateRay(IPoint, Ray->Initial, I[i].d, Ray->Direction);
  140.  
  141.       if (Point_In_Clip(IPoint, Object->Clip))
  142.       {
  143.         push_entry_i1(I[i].d,IPoint,Object,I[i].t,Depth_Stack);
  144.  
  145.         Intersection_Found = TRUE;
  146.       }
  147.     }
  148.   }
  149.  
  150.   return (Intersection_Found);
  151. }
  152.  
  153.  
  154.  
  155. /*****************************************************************************
  156. *
  157. * FUNCTION
  158. *
  159. *   intersect_cone
  160. *
  161. * INPUT
  162. *   
  163. * OUTPUT
  164. *   
  165. * RETURNS
  166. *   
  167. * AUTHOR
  168. *
  169. *   Alexander Enzmann
  170. *   
  171. * DESCRIPTION
  172. *
  173. *   -
  174. *
  175. * CHANGES
  176. *
  177. *   -
  178. *
  179. ******************************************************************************/
  180.  
  181. static int intersect_cone(Ray, Cone, Intersection)
  182. RAY *Ray;
  183. CONE *Cone;
  184. CONE_INT *Intersection;
  185. {
  186.   int i = 0;
  187.   DBL rdiv;
  188.   DBL a, b, c, z, t1, t2, len;
  189.   DBL d;
  190.   VECTOR P, D;
  191.  
  192.   Increase_Counter(stats[Ray_Cone_Tests]);
  193.  
  194.   /* Transform the ray into the cones space */
  195.  
  196.   MInvTransPoint(P, Ray->Initial, Cone->Trans);
  197.   MInvTransDirection(D, Ray->Direction, Cone->Trans);
  198.  
  199.   VLength(len, D);
  200.   VInverseScaleEq(D, len);
  201.  
  202.   if (Test_Flag(Cone, CYLINDER_FLAG))
  203.   {
  204.     /* Solve intersections with a cylinder */
  205.  
  206.     a = D[X] * D[X] + D[Y] * D[Y];
  207.  
  208.     if (a > EPSILON)
  209.     {
  210.       b = P[X] * D[X] + P[Y] * D[Y];
  211.  
  212.       c = P[X] * P[X] + P[Y] * P[Y] - 1.0;
  213.  
  214.       d = b * b - a * c;
  215.  
  216.       if (d >= 0.0)
  217.       {
  218.         d = sqrt(d);
  219.  
  220. /*
  221.         t1 = (-b + d) / a;
  222.         t2 = (-b - d) / a;
  223. */
  224.     rdiv = (1.0 / a);
  225.         t1 = (-b + d) * rdiv;
  226.         t2 = (-b - d) * rdiv;
  227.  
  228.         z = P[Z] + t1 * D[Z];
  229.  
  230.         if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0))
  231.         {
  232.           Intersection[i].d   = t1 / len;
  233.           Intersection[i++].t = SIDE_HIT;
  234.         }
  235.  
  236.         z = P[Z] + t2 * D[Z];
  237.  
  238.         if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0))
  239.         {
  240.           Intersection[i].d   = t2 / len;
  241.           Intersection[i++].t = SIDE_HIT;
  242.         }
  243.       }
  244.     }
  245.   }
  246.   else
  247.   {
  248.     /* Solve intersections with a cone */
  249.  
  250.     a = D[X] * D[X] + D[Y] * D[Y] - D[Z] * D[Z];
  251.  
  252.     b = D[X] * P[X] + D[Y] * P[Y] - D[Z] * P[Z];
  253.  
  254.     c = P[X] * P[X] + P[Y] * P[Y] - P[Z] * P[Z];
  255.  
  256.     if (fabs(a) < EPSILON)
  257.     {
  258.       if (fabs(b) > EPSILON)
  259.       {
  260.         /* One intersection */
  261.  
  262.         t1 = -0.5 * c / b;
  263.  
  264.         z = P[Z] + t1 * D[Z];
  265.  
  266.         if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
  267.         {
  268.           Intersection[i].d   = t1 / len;
  269.           Intersection[i++].t = SIDE_HIT;
  270.         }
  271.       }
  272.     }
  273.     else
  274.     {
  275.       /* Check hits against the side of the cone */
  276.  
  277.       d = b * b - a * c;
  278.  
  279.       if (d >= 0.0)
  280.       {
  281.         d = sqrt(d);
  282.  
  283.     rdiv = (1.0 / a);
  284.         t1 = (-b - d) * rdiv;
  285.         t2 = (-b + d) * rdiv;
  286.  
  287. /*
  288.         t1 = (-b - d) / a;
  289.         t2 = (-b + d) / a;
  290. */
  291.  
  292.         z = P[Z] + t1 * D[Z];
  293.  
  294.         if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
  295.         {
  296.           Intersection[i].d   = t1 / len;
  297.           Intersection[i++].t = SIDE_HIT;
  298.         }
  299.  
  300.         z = P[Z] + t2 * D[Z];
  301.  
  302.         if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
  303.         {
  304.           Intersection[i].d   = t2 / len;
  305.           Intersection[i++].t = SIDE_HIT;
  306.         }
  307.       }
  308.     }
  309.   }
  310.  
  311.   if (Test_Flag(Cone, CLOSED_FLAG) && (fabs(D[Z]) > EPSILON))
  312.   {
  313.     d = (1.0 - P[Z]) / D[Z];
  314.  
  315.     a = (P[X] + d * D[X]);
  316.  
  317.     b = (P[Y] + d * D[Y]);
  318.  
  319.     if (((Sqr(a) + Sqr(b)) <= 1.0) && (d > Cone_Tolerance) && (d < Max_Distance))
  320.     {
  321.       Intersection[i].d   = d / len;
  322.       Intersection[i++].t = CAP_HIT;
  323.     }
  324.  
  325.     d = (Cone->dist - P[Z]) / D[Z];
  326.  
  327.     a = (P[X] + d * D[X]);
  328.  
  329.     b = (P[Y] + d * D[Y]);
  330.  
  331.     if ((Sqr(a) + Sqr(b)) <= (Test_Flag(Cone, CYLINDER_FLAG) ? 1.0 : Sqr(Cone->dist))
  332.       && (d > Cone_Tolerance) && (d < Max_Distance))
  333.     {
  334.       Intersection[i].d   = d / len;
  335.       Intersection[i++].t = BASE_HIT;
  336.     }
  337.   }
  338.  
  339.   if (i)
  340.   {
  341.     Increase_Counter(stats[Ray_Cone_Tests_Succeeded]);
  342.   }
  343.  
  344.   return (i);
  345. }
  346.  
  347.  
  348.  
  349. /*****************************************************************************
  350. *
  351. * FUNCTION
  352. *
  353. *   Inside_Cone
  354. *
  355. * INPUT
  356. *   
  357. * OUTPUT
  358. *   
  359. * RETURNS
  360. *   
  361. * AUTHOR
  362. *
  363. *   Alexander Enzmann
  364. *   
  365. * DESCRIPTION
  366. *
  367. *   -
  368. *
  369. * CHANGES
  370. *
  371. *   -
  372. *
  373. ******************************************************************************/
  374.  
  375. static int Inside_Cone(IPoint, Object)
  376. VECTOR IPoint;
  377. OBJECT *Object;
  378. {
  379.   CONE *Cone = (CONE *)Object;
  380.   DBL w2, z2, offset = (Test_Flag(Cone, CLOSED_FLAG) ? -EPSILON : EPSILON);
  381.   VECTOR New_Point;
  382.  
  383.   /* Transform the point into the cones space */
  384.  
  385.   MInvTransPoint(New_Point, IPoint, Cone->Trans);
  386.  
  387.   /* Test to see if we are inside the cone */
  388.  
  389.   w2 = New_Point[X] * New_Point[X] + New_Point[Y] * New_Point[Y];
  390.  
  391.   if (Test_Flag(Cone, CYLINDER_FLAG))
  392.   {
  393.     /* Check to see if we are inside a cylinder */
  394.  
  395.     if ((w2 > 1.0 + offset) ||
  396.         (New_Point[Z] < 0.0 - offset) ||
  397.         (New_Point[Z] > 1.0 + offset))
  398.     {
  399.       return (Test_Flag(Cone, INVERTED_FLAG));
  400.     }
  401.     else
  402.     {
  403.       return (!Test_Flag(Cone, INVERTED_FLAG));
  404.     }
  405.   }
  406.   else
  407.   {
  408.     /* Check to see if we are inside a cone */
  409.  
  410.     z2 = New_Point[Z] * New_Point[Z];
  411.  
  412.     if ((w2 > z2 + offset) ||
  413.         (New_Point[Z] < Cone->dist - offset) ||
  414.         (New_Point[Z] > 1.0+offset))
  415.     {
  416.       return (Test_Flag(Cone, INVERTED_FLAG));
  417.     }
  418.     else
  419.     {
  420.       return (!Test_Flag(Cone, INVERTED_FLAG));
  421.     }
  422.   }
  423. }
  424.  
  425.  
  426.  
  427. /*****************************************************************************
  428. *
  429. * FUNCTION
  430. *
  431. *   Cone_Normal
  432. *
  433. * INPUT
  434. *
  435. * OUTPUT
  436. *
  437. * RETURNS
  438. *
  439. * AUTHOR
  440. *
  441. *   Alexander Enzmann
  442. *
  443. * DESCRIPTION
  444. *
  445. *   -
  446. *
  447. * CHANGES
  448. *
  449. *   -
  450. *
  451. ******************************************************************************/
  452.  
  453. static void Cone_Normal(Result, Object, Inter)
  454. OBJECT *Object;
  455. VECTOR Result;
  456. INTERSECTION *Inter;
  457. {
  458.   CONE *Cone = (CONE *)Object;
  459.  
  460.   /* Transform the point into the cones space */
  461.  
  462.   MInvTransPoint(Result, Inter->IPoint, Cone->Trans);
  463.  
  464.   /* Calculating the normal is real simple in canonical cone space */
  465.  
  466.   switch (Inter->i1)
  467.   {
  468.     case SIDE_HIT:
  469.  
  470.       if (Test_Flag(Cone, CYLINDER_FLAG))
  471.       {
  472.         Result[Z] = 0.0;
  473.       }
  474.       else
  475.       {
  476.         Result[Z] = -Result[Z];
  477.       }
  478.  
  479.       break;
  480.  
  481.     case BASE_HIT:
  482.  
  483.       Make_Vector(Result, 0.0, 0.0, -1.0)
  484.  
  485.       break;
  486.  
  487.     case CAP_HIT:
  488.  
  489.       Make_Vector(Result, 0.0, 0.0, 1.0)
  490.  
  491.       break;
  492.   }
  493.  
  494.   /* Transform the point out of the cones space */
  495.  
  496.   MTransNormal(Result, Result, Cone->Trans);
  497.  
  498.   VNormalize(Result, Result);
  499. }
  500.  
  501.  
  502.  
  503. /*****************************************************************************
  504. *
  505. * FUNCTION
  506. *
  507. *   Translate_Cone
  508. *
  509. * INPUT
  510. *
  511. * OUTPUT
  512. *
  513. * RETURNS
  514. *
  515. * AUTHOR
  516. *
  517. *   Alexander Enzmann
  518. *
  519. * DESCRIPTION
  520. *
  521. *   -
  522. *
  523. * CHANGES
  524. *
  525. *   -
  526. *
  527. ******************************************************************************/
  528.  
  529. static void Translate_Cone(Object, Vector, Trans)
  530. OBJECT *Object;
  531. VECTOR Vector;
  532. TRANSFORM *Trans;
  533. {
  534.   Transform_Cone(Object, Trans);
  535. }
  536.  
  537.  
  538.  
  539. /*****************************************************************************
  540. *
  541. * FUNCTION
  542. *
  543. *   Rotate_Cone
  544. *
  545. * INPUT
  546. *
  547. * OUTPUT
  548. *
  549. * RETURNS
  550. *
  551. * AUTHOR
  552. *
  553. *   Alexander Enzmann
  554. *
  555. * DESCRIPTION
  556. *
  557. *   -
  558. *
  559. * CHANGES
  560. *
  561. *   -
  562. *
  563. ******************************************************************************/
  564.  
  565. static void Rotate_Cone(Object, Vector, Trans)
  566. OBJECT *Object;
  567. VECTOR Vector;
  568. TRANSFORM *Trans;
  569. {
  570.   Transform_Cone(Object, Trans);
  571. }
  572.  
  573.  
  574.  
  575. /*****************************************************************************
  576. *
  577. * FUNCTION
  578. *
  579. *   Scale_Cone
  580. *
  581. * INPUT
  582. *
  583. * OUTPUT
  584. *
  585. * RETURNS
  586. *
  587. * AUTHOR
  588. *
  589. *   Alexander Enzmann
  590. *
  591. * DESCRIPTION
  592. *
  593. *   -
  594. *
  595. * CHANGES
  596. *
  597. *   -
  598. *
  599. ******************************************************************************/
  600.  
  601. static void Scale_Cone(Object, Vector, Trans)
  602. OBJECT *Object;
  603. VECTOR Vector;
  604. TRANSFORM *Trans;
  605. {
  606.   Transform_Cone(Object, Trans);
  607. }
  608.  
  609.  
  610.  
  611. /*****************************************************************************
  612. *
  613. * FUNCTION
  614. *
  615. *   Transform_Cone
  616. *
  617. * INPUT
  618. *
  619. * OUTPUT
  620. *
  621. * RETURNS
  622. *
  623. * AUTHOR
  624. *
  625. *   Alexander Enzmann
  626. *
  627. * DESCRIPTION
  628. *
  629. *   -
  630. *
  631. * CHANGES
  632. *
  633. *   -
  634. *
  635. ******************************************************************************/
  636.  
  637. static void Transform_Cone(Object, Trans)
  638. OBJECT *Object;
  639. TRANSFORM *Trans;
  640. {
  641.   CONE *Cone = (CONE *)Object;
  642.  
  643.   Compose_Transforms(Cone->Trans, Trans);
  644.  
  645.   Compute_Cone_BBox(Cone);
  646. }
  647.  
  648.  
  649.  
  650. /*****************************************************************************
  651. *
  652. * FUNCTION
  653. *
  654. *   Invert_Cone
  655. *
  656. * INPUT
  657. *
  658. * OUTPUT
  659. *
  660. * RETURNS
  661. *
  662. * AUTHOR
  663. *
  664. *   Alexander Enzmann
  665. *
  666. * DESCRIPTION
  667. *
  668. *   -
  669. *
  670. * CHANGES
  671. *
  672. *   -
  673. *
  674. ******************************************************************************/
  675.  
  676. static void Invert_Cone(Object)
  677. OBJECT *Object;
  678. {
  679.   Invert_Flag(Object, INVERTED_FLAG);
  680. }
  681.  
  682.  
  683.  
  684. /*****************************************************************************
  685. *
  686. * FUNCTION
  687. *
  688. *   Create_Cone
  689. *
  690. * INPUT
  691. *
  692. * OUTPUT
  693. *
  694. * RETURNS
  695. *
  696. * AUTHOR
  697. *
  698. *   Alexander Enzmann
  699. *
  700. * DESCRIPTION
  701. *
  702. *   -
  703. *
  704. * CHANGES
  705. *
  706. *   -
  707. *
  708. ******************************************************************************/
  709.  
  710. CONE *Create_Cone()
  711. {
  712.   CONE *New;
  713.  
  714.   New = (CONE *)POV_MALLOC(sizeof(CONE), "cone");
  715.  
  716.   INIT_OBJECT_FIELDS(New, CONE_OBJECT, &Cone_Methods)
  717.  
  718.   Make_Vector(New->apex, 0.0, 0.0, 1.0);
  719.   Make_Vector(New->base, 0.0, 0.0, 0.0);
  720.  
  721.   New->apex_radius = 1.0;
  722.   New->base_radius = 0.0;
  723.  
  724.   New->dist = 0.0;
  725.  
  726.   New->Trans = Create_Transform();
  727.  
  728.   /* Cone/Cylinder has capped ends by default. */
  729.  
  730.   Set_Flag(New, CLOSED_FLAG);
  731.  
  732.   /* Default bounds */
  733.  
  734.   Make_BBox(New->BBox, -1.0, -1.0, 0.0, 2.0, 2.0, 1.0);
  735.  
  736.   return (New);
  737. }
  738.  
  739.  
  740.  
  741. /*****************************************************************************
  742. *
  743. * FUNCTION
  744. *
  745. *   Copy_Cone
  746. *
  747. * INPUT
  748. *
  749. * OUTPUT
  750. *
  751. * RETURNS
  752. *
  753. * AUTHOR
  754. *
  755. *   Alexander Enzmann
  756. *
  757. * DESCRIPTION
  758. *
  759. *   -
  760. *
  761. * CHANGES
  762. *
  763. *   -
  764. *
  765. ******************************************************************************/
  766.  
  767. static void *Copy_Cone(Object)
  768. OBJECT *Object;
  769. {
  770.   CONE *New;
  771.  
  772.   New = Create_Cone();
  773.  
  774.   /* Get rid of the transformation created in Create_Cone(). */
  775.  
  776.   Destroy_Transform(New->Trans);
  777.  
  778.   /* Copy cone. */
  779.  
  780.   *New = *((CONE *)Object);
  781.  
  782.   New->Trans = Copy_Transform(((CONE *)Object)->Trans);
  783.  
  784.   return (New);
  785. }
  786.  
  787.  
  788.  
  789. /*****************************************************************************
  790. *
  791. * FUNCTION
  792. *
  793. *   Create_Cylinder
  794. *
  795. * INPUT
  796. *
  797. * OUTPUT
  798. *
  799. * RETURNS
  800. *
  801. * AUTHOR
  802. *
  803. *   Alexander Enzmann
  804. *
  805. * DESCRIPTION
  806. *
  807. *   -
  808. *
  809. * CHANGES
  810. *
  811. *   -
  812. *
  813. ******************************************************************************/
  814.  
  815. CONE *Create_Cylinder()
  816. {
  817.   CONE *New;
  818.  
  819.   New = (CONE *)POV_MALLOC(sizeof(CONE), "cone");
  820.  
  821.   INIT_OBJECT_FIELDS(New, CONE_OBJECT, &Cone_Methods)
  822.  
  823.   Make_Vector(New->apex, 0.0, 0.0, 1.0);
  824.   Make_Vector(New->base, 0.0, 0.0, 0.0);
  825.  
  826.   New->apex_radius = 1.0;
  827.   New->base_radius = 1.0;
  828.   New->dist        = 0.0;
  829.  
  830.   New->Trans = Create_Transform();
  831.  
  832.   Set_Flag(New, CYLINDER_FLAG); /* This is a cylinder. */
  833.   Set_Flag(New, CLOSED_FLAG);   /* Has capped ends.    */
  834.  
  835.   /* Default bounds */
  836.  
  837.   Make_BBox(New->BBox, -1.0, -1.0, 0.0, 2.0, 2.0, 1.0);
  838.  
  839.   return (New);
  840. }
  841.  
  842.  
  843.  
  844. /*****************************************************************************
  845. *
  846. * FUNCTION
  847. *
  848. *   Compute_Cone_Data
  849. *
  850. * INPUT
  851. *
  852. * OUTPUT
  853. *
  854. * RETURNS
  855. *
  856. * AUTHOR
  857. *
  858. *   Alexander Enzmann
  859. *
  860. * DESCRIPTION
  861. *
  862. *   -
  863. *
  864. * CHANGES
  865. *
  866. *   Feb 1996: check for equal sized ends (cylinder) first [AED]
  867. *
  868. ******************************************************************************/
  869.  
  870. void Compute_Cone_Data(Object)
  871. OBJECT *Object;
  872. {
  873.   DBL tlen, len, tmpf;
  874.   VECTOR tmpv, axis, origin;
  875.   CONE *Cone = (CONE *)Object;
  876.  
  877.   /* Process the primitive specific information */
  878.  
  879.   if (fabs(Cone->apex_radius - Cone->base_radius) < EPSILON)
  880.   {
  881.     /* What we are dealing with here is really a cylinder */
  882.  
  883.     Set_Flag(Cone, CYLINDER_FLAG);
  884.  
  885.     Compute_Cylinder_Data(Object);
  886.  
  887.     return;
  888.   }
  889.  
  890.   if (Cone->apex_radius < Cone->base_radius)
  891.   {
  892.     /* Want the bigger end at the top */
  893.  
  894.     Assign_Vector(tmpv,Cone->base);
  895.     Assign_Vector(Cone->base,Cone->apex);
  896.     Assign_Vector(Cone->apex,tmpv);
  897.  
  898.     tmpf = Cone->base_radius;
  899.     Cone->base_radius = Cone->apex_radius;
  900.     Cone->apex_radius = tmpf;
  901.   }
  902.  
  903.   /* Find the axis and axis length */
  904.  
  905.   VSub(axis, Cone->apex, Cone->base);
  906.  
  907.   VLength(len, axis);
  908.  
  909.   if (len < EPSILON)
  910.   {
  911.     Error("Degenerate cone/cylinder.\n");
  912.   }
  913.   else
  914.   {
  915.     VInverseScaleEq(axis, len)
  916.   }
  917.  
  918.   /* Determine alignment */
  919.  
  920.   tmpf = Cone->base_radius * len / (Cone->apex_radius - Cone->base_radius);
  921.  
  922.   VScale(origin, axis, tmpf);
  923.  
  924.   VSub(origin, Cone->base, origin);
  925.  
  926.   tlen = tmpf + len;
  927.  
  928.   Cone->dist = tmpf / tlen;
  929.  
  930.   Compute_Coordinate_Transform(Cone->Trans, origin, axis, Cone->apex_radius, tlen);
  931.  
  932.   /* Recalculate the bounds */
  933.  
  934.   Compute_Cone_BBox(Cone);
  935. }
  936.  
  937.  
  938.  
  939. /*****************************************************************************
  940. *
  941. * FUNCTION
  942. *
  943. *   Compute_Cylinder_Data
  944. *
  945. * INPUT
  946. *
  947. * OUTPUT
  948. *
  949. * RETURNS
  950. *
  951. * AUTHOR
  952. *
  953. *   Alexander Enzmann
  954. *
  955. * DESCRIPTION
  956. *
  957. *   -
  958. *
  959. * CHANGES
  960. *
  961. *   -
  962. *
  963. ******************************************************************************/
  964.  
  965. void Compute_Cylinder_Data(Object)
  966. OBJECT *Object;
  967. {
  968.   DBL tmpf;
  969.   VECTOR axis;
  970.   CONE *Cone = (CONE *)Object;
  971.  
  972.   VSub(axis, Cone->apex, Cone->base);
  973.  
  974.   VLength(tmpf, axis);
  975.  
  976.   if (tmpf < EPSILON)
  977.   {
  978.     Error("Degenerate cylinder, base point = apex point.\n");
  979.   }
  980.   else
  981.   {
  982.     VInverseScaleEq(axis, tmpf)
  983.  
  984.     Compute_Coordinate_Transform(Cone->Trans, Cone->base, axis, Cone->apex_radius, tmpf);
  985.   }
  986.  
  987.   Cone->dist = 0.0;
  988.  
  989.   /* Recalculate the bounds */
  990.  
  991.   Compute_Cone_BBox(Cone);
  992. }
  993.  
  994.  
  995.  
  996.  
  997. /*****************************************************************************
  998. *
  999. * FUNCTION
  1000. *
  1001. *   Destroy_Cone
  1002. *
  1003. * INPUT
  1004. *
  1005. * OUTPUT
  1006. *
  1007. * RETURNS
  1008. *
  1009. * AUTHOR
  1010. *
  1011. *   Alexander Enzmann
  1012. *
  1013. * DESCRIPTION
  1014. *
  1015. *   -
  1016. *
  1017. * CHANGES
  1018. *
  1019. *   -
  1020. *
  1021. ******************************************************************************/
  1022.  
  1023. static void Destroy_Cone(Object)
  1024. OBJECT *Object;
  1025. {
  1026.   Destroy_Transform(((CONE *)Object)->Trans);
  1027.  
  1028.   POV_FREE (Object);
  1029. }
  1030.  
  1031.  
  1032.  
  1033. /*****************************************************************************
  1034. *
  1035. * FUNCTION
  1036. *
  1037. *   Compute_Cone_BBox
  1038. *
  1039. * INPUT
  1040. *
  1041. *   Cone - Cone/Cylinder
  1042. *
  1043. * OUTPUT
  1044. *
  1045. *   Cone
  1046. *
  1047. * RETURNS
  1048. *
  1049. * AUTHOR
  1050. *
  1051. *   Dieter Bayer
  1052. *
  1053. * DESCRIPTION
  1054. *
  1055. *   Calculate the bounding box of a cone or cylinder.
  1056. *
  1057. * CHANGES
  1058. *
  1059. *   Aug 1994 : Creation.
  1060. *
  1061. ******************************************************************************/
  1062.  
  1063. void Compute_Cone_BBox(Cone)
  1064. CONE *Cone;
  1065. {
  1066.   Make_BBox(Cone->BBox, -1.0, -1.0, 0.0, 2.0, 2.0, 1.0);
  1067.  
  1068.   Recompute_BBox(&Cone->BBox, Cone->Trans);
  1069. }
  1070.  
  1071.